package com.yonyou.gmcc.gateway.web.service;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;

import javax.servlet.Filter;
import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import com.google.common.collect.Maps;
import com.yonyou.gmcc.gateway.web.dao.TmResourceMapper;
import com.yonyou.gmcc.gateway.web.entity.TmResourceVo;
import com.yonyou.gmcc.gateway.web.shiro.SimpleRoleAuthorizationFilter;

@Component
public class PermissionInition implements InitializingBean,DisposableBean, ApplicationListener<ContextRefreshedEvent> {

	private static Logger logger=Logger.getLogger(PermissionInition.class);
    @Autowired
    private ApplicationContext context;
	@Autowired
	private TmResourceMapper tmResourceMapper;
	@Autowired
	@Qualifier("shiroFilter")
	private ShiroFilterFactoryBean factory;
    private static boolean inited=false;

	@Override
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void afterPropertiesSet() throws Exception {
	}

	
	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		//if(event.getApplicationContext().getParent() == null){ 
		if(!inited){
			logger.info("----开始初始化权限数据(resc,role)");
	        this.inited=true;
	        initPermission();
		}
		//}
	}
	public void initPermission(){

        AbstractShiroFilter shiroFilter = null;
		try {
			shiroFilter = (AbstractShiroFilter) factory.getObject();
		} catch (Exception e) {
			throw new RuntimeException(
					"get ShiroFilter from shiroFilterFactoryBean error!");
		}

		PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
				.getFilterChainResolver();
		DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver
				.getFilterChainManager();

		// 清空老的权限过滤器
		manager.getFilterChains().clear();
		
		// 清空老的权限控制
		factory.getFilterChainDefinitionMap().clear();
		factory.setFilterChainDefinitionMap(loadFilterChainDefinitions());

//        Map<String, Filter>filters = Maps.newHashMap();  
//        filters.put("role", new SimpleRoleAuthorizationFilter());
//        factory.setFilters(filters);  
//        Map<String, Filter>filter =manager.getFilters();
//		manager.setFilters(filters);
        
		// 重新构建生成
		Map<String, String> chains = factory.getFilterChainDefinitionMap();
		for (Map.Entry<String, String> entry : chains.entrySet()) {
			String url = entry.getKey();
			String chainDefinition = entry.getValue().trim()
					.replace(" ", "");
			manager.createChain(url, chainDefinition);
		}

		logger.info("更新权限成功！！");
	}
	public Map<String, String> loadFilterChainDefinitions(){
        List<TmResourceVo> vos=tmResourceMapper.selectResourceWithRole(null);
        String curUri="";
    	String roles="";
    	TmResourceVo lastVo=null;
    	if(vos.size()>0) 
    		curUri=vos.get(0).getResUri();
    	Map<String, String> chains=Maps.newHashMap();
        for(TmResourceVo vo:vos){
          	if(!curUri.equals(vo.getResUri())){
    	        	chains.put(curUri, "role[\""+roles.substring(0, roles.length()-1)+"\"]");
    	        	roles="";
          	}
          	curUri=vo.getResUri();
          	lastVo=vo;
          	roles= roles+vo.getRoleId()+",";
          }
          if(lastVo!=null){
          	chains.put(lastVo.getResUri(), "role[\""+roles.substring(0, roles.length()-1)+"\"]");
          }
          //确保所有的url必须有角色授权
          //chains.put("/**", "role[abc]");  
          chains.put("/comp/**", "authc"); 
          logger.info("-----(resc,role)="+chains.toString());
          return chains;
	}
	private void init(){

        List<TmResourceVo> vos=tmResourceMapper.selectResourceWithRole(null);
        String curUri="";
    	String roles="";
    	TmResourceVo lastVo=null;
    	if(vos.size()>0) 
    		curUri=vos.get(0).getResUri();
        Map<String, String> chains = factory.getFilterChainDefinitionMap() ;
      chains.put("/manager/login", "anon");  
      chains.put("/manager/unauthor", "anon");  
      chains.put("/manager/logout", "logout");  
      chains.put("/manager/base/**", "anon");  
      chains.put("/wechatcall/**", "roles[admin]");  
      //chains.put("/wechatcall/test", "roles[\"admin,super\"]");  
      chains.put("/wechatcall/test", "role[\"admin,super\"]");  
      chains.put("/user/edit/**", "perms[admin:edit:*]");  
      chains.put("/comp/**", "roles[admin]"); 
//      chains.put("/comp/**", "authc"); 
      chains.put("/css/**", "anon");  
      chains.put("/layer/**", "anon");  
      chains.put("/html/**", "anon");  
      chains.put("/**", "authc,perms"); 
//        for(TmResourceVo vo:vos){
//        	if(!curUri.equals(vo.getResUri())){
//	        	chains.put(curUri, "role[\""+roles.substring(0, roles.length()-1)+"\"]");
//	        	roles="";
//        	}
//        	curUri=vo.getResUri();
//        	lastVo=vo;
//        	roles= roles+vo.getRoleId()+",";
//        }
//        if(lastVo!=null){
//        	chains.put(lastVo.getResUri(), "role[\""+roles.substring(0, roles.length()-1)+"\"]");
//        }
//        //确保所有的url必须有角色授权
//        //chains.put("/**", "role[abc]");  
//    	logger.info("-----(resc,role)="+chains.toString());
//        factory.setFilterChainDefinitionMap(chains);  
	}
}
